#ifndef __I_UNIX_NET_VCONNECT_H__
#define __I_UNIX_NET_VCONNECT_H__

#include <zlib/eventsystem/I_Buffer.h>
#include "I_NetHandler.h"
#include "I_UnixNet.h"

#define NET_EVENT_ACCEPT 			(NET_EVENT_START+1)
#define NET_EVENT_CONNECT			(NET_EVENT_START+2)
#define VC_EVENT_READ_READY			(NET_EVENT_START+3)
#define VC_EVENT_READ_COMPLATE		(NET_EVENT_START+4)
#define VC_EVENT_WRITE_READY		(NET_EVENT_START+5)
#define VC_EVENT_WRITE_COMPLATE		(NET_EVENT_START+6)
#define VC_EVENT_EOS				(NET_EVENT_START+7)
#define VC_EVENT_ERROR				(NET_EVENT_START+8)

#define NET_SHUTDOWN_NONE 			0
#define NET_SHUTDOWN_READ 			1
#define NET_SHUTDOWN_WRITE 			2
#define NET_SHUTDOWN_READWRITE		3

#define NET_MAX_IOV					8

class UnixNetVConnect;

//IO View
//we can get io state by IO View.
//the IO View is only reader or writer
class VIO
{
public:
	enum{
		NONE = 0,
		READER,
		WRITER
	};

	VIO();
	//the amount that has been complate
	int64_t ndone;

	//call with events for this operation
	Continuation *_cont;
	//the total number of bytes to be done
	int64_t _nbytes;
	//reader
	IOBufferReader *_reader;
	//writer
	MIOBuffer *_writer;

	UnixNetVConnect *vc;
	//this io view is reader or writer?
	int op;

	Ptr<ProxyMutex> mutex;

	//functions
	void init_reader(Continuation *, int64_t, MIOBuffer *writer);
	void init_writer(Continuation *, int64_t, IOBufferReader *reader);
	void set_continuation(Continuation *);
	void set_reader(IOBufferReader *);
	void set_writer(MIOBuffer *);

	void reenable();

	void update(int64_t len);

	int64_t ntodo();
};

class NetState
{
public:
	VIO vio;
	bool in_enable_list;
	bool triggered;
	volatile bool enabled;

	NetState();
};

enum ShutDownHowTo_t
{
	IO_SHUTDOWN_READ = 0,
	IO_SHUTDOWN_WRITE,
	IO_SHUTDOWN_READWRITE
};

class UnixNetVConnect : public Continuation
{
public:

	//interface
	VIO *do_io_read(Continuation *, MIOBuffer *, int64_t nbytes = INT64_MAX);
	VIO *do_io_write(Continuation *, IOBufferReader *, int64_t nbytes = INT64_MAX);
	void do_io_close(int alerrno);
	void do_io_shutdown(ShutDownHowTo_t how);
	void reenable(VIO *vio);

	int acceptEvent(int event, void *data);
	int connectEvent(int event, void *data);

	//only allow call this functin in NetHanadler.process_ready_list
	void read_from_net();
	void write_to_net();

	//private function
	void read_reschedule();
	void write_reschedule();

	//disable
	void read_disable();
	void write_disable();

	//signal notification
	int read_signal_update(int event);
	int write_signal_update(int event);
	int read_signal_done(int event);
	int write_signal_done(int event);
	int read_signal_error(int aerrno);
	int write_signal_error(int aerrno);

	int fd;
	Connection conn;
	EventIO ep;
	NetHandler *nh;
	NetState read;
	NetState write;
	bool closed;
	Action _action;
	NetOptions opt;
	int lerr;

	unsigned int f_shutdown : 2;

	//Reentry counter
	int reentry_counter;

	UnixNetVConnect();
};


#endif //__I_UNIX_NET_VCONNECT_H__
